﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Atmk.WaterMeter.MIS.Commons.Interfaces;
using Atmk.WaterMeter.MIS.Commons.Interfaces.GateWay;
using Atmk.WaterMeter.MIS.Commons.Utils;
using Atmk.WaterMeter.MIS.Datas;
using Atmk.WaterMeter.MIS.Entities;
using Atmk.WaterMeter.MIS.Entities.Enums;
using Atmk.WaterMeter.MIS.Entities.Models;
using Atmk.WaterMeter.MIS.GateWay.CT_NBIoT;
using Atmk.WaterMeter.MIS.GateWay.CT_NBIoT.ViewModel.Sundry;
using Newtonsoft.Json;
using NLog;

namespace Atmk.WaterMeter.MIS.Logic
{
    /// <summary>
    ///     电信平台的水表指令发送
    /// </summary>
    public class CT_NBIoT_CommandSender : ICommandSender
    {
        private readonly ICT_NBIoT_CommandSenderHelper _ctNbioTCommandSenderHelper;
        private readonly Logger _logger = LogManager.GetCurrentClassLogger();

        private readonly IRepository _repository;

        private Dictionary<string, string> _CommandMap = new Dictionary<string, string>();

        public CT_NBIoT_CommandSender(IRepository repository,
            ICT_NBIoT_CommandSenderHelper ctNbioTCommandSenderHelper)
        {
            _repository = repository;
            _ctNbioTCommandSenderHelper = ctNbioTCommandSenderHelper;
            LoadMap();
        }

        /// <summary>
        /// 执行抄表指令
        /// </summary>
        /// <param name="command"></param>
        /// <param name="commandType"></param>
        public CommandStatus Send(ref MeterCommand command, CommandType commandType)
        {
            _logger.Info("Ct_Iot里发送抄表指令");
            //如果设备不再mapping里，返回异常
            if (!_CommandMap.ContainsKey(command.MeterNumber))
            {
                _logger.Warn("水表号不在电信设备映射列表里,检查该设备是否在电信设备列表里");
                return CommandStatus.执行失败;
            }

            if (commandType == CommandType.抄表指令) return ReadNowMeter(command);
            if (commandType == CommandType.开阀指令 || commandType == CommandType.关阀指令)
            {
                var tapStatus = commandType == CommandType.开阀指令 ? 1 : 0;
                return OpenTapMeter(ref command, tapStatus);
            }

            //执行
            return CommandStatus.未发送;
        }

        private void LoadMap()
        {
            try
            {
                _logger.Info("读取水表号与电信平台ID对应列表");
                using (var _context = ContextBuilder.Build())
                {
                    var mapLis = _context.Meter.ToList();
                    _CommandMap = mapLis.ToDictionary(key => key.MeterNumber, value => value.CtdeviceId);
                }

            }
            catch (Exception e)
            {
                _logger.Error($"map对应失败{e.Message}");
                _logger.Error($"{e.StackTrace}");
                _CommandMap["102010000987"] = "c4218462-bfc1-4b9a-b4b3-7616faaf3f7a";
                _CommandMap["102010000009"] = "9342a13b-d6a6-4e2d-bc82-e5fdfc5de574";
            }
        }

        /// <summary>
        ///     读取当前时间最新历史数据并保存
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        private CommandStatus ReadNowMeter(MeterCommand command)
        {
            //读取Map获取水表id
            if (_CommandMap.ContainsKey(command.MeterNumber))
            {
                //获取当前时间抄表数据
                var res = _ctNbioTCommandSenderHelper.ReadDataHistory(_CommandMap[command.MeterNumber])
                    .Where(r => r.GetTime.Date == DateTime.Now.Date).OrderByDescending(r => r.GetTime).ToList();
                //判断水表当前时间有无抄表数据
                if (res.Count > 0)
                {
                    var readMeter = res.First();
                    //获取最新水表数据
                    using (var _context = ContextBuilder.Build()) 
                    {
                        var meter=_context.Meter.FirstOrDefault(m=>m.MeterNumber== command.MeterNumber);
                       var meters = _repository.FindAll<MeterReadingRecord>()
                        .Where(m=>m.CtdeviceId == meter.CtdeviceId)
                        .OrderByDescending(r => r.ReadTime).ToList();
                    //判断有无该时间的水表数据
                    if (!meters.Any(m => m.ReadTime >= readMeter.GetTime))
                    {
                        double last = 0;
                        if (meters.Any()) last = meters.First().Value;
                        //水表读数
                        var byteRead = Base64Convert.ConvertBytes(readMeter.Data.current);
                        var reading = BytesConvert.BitConvertInts(byteRead, 6).First()/100.00;
                        //var reading = BytesConvert.BitConvertByteForStringInt(byteRead) / 100;
                        var record = new MeterReadingRecord
                        {
                            //Number = command.MeterNumber,
                            ReadTime = readMeter.GetTime,
                            Value =  reading,
                            //LastValue = last,
                            ValveState = readMeter.Data.valve == 1 ? (int)ValveState.Opening : (int)ValveState.Closed,
                            //Voltage = Simple.RundVoltage(),//TODO:临时
                            //((readMeter.Data.voltage + 100) * 0.01).ToString(CultureInfo.InvariantCulture),
                            //Voltage = (readMeter.Data.voltage + 100) * 0.01,
                            //CloseState = (int)CloseState.UnCLose
                        };
                        //_repository.Add(record);

                    }
                    }
                     
                }

                return CommandStatus.执行成功;
            }

            return CommandStatus.未发送;
        }

        /// <summary>
        ///     执行开关阀指令
        /// </summary>
        /// <param name="commands"></param>
        /// <param name="tapStatus"></param>
        /// <returns></returns>
        private CommandStatus OpenTapMeter(ref MeterCommand commands, int tapStatus)
        {
            //读取Map获取水表id
            if (_CommandMap.ContainsKey(commands.MeterNumber))
            {
                //执行命令并获取指令Id
                var res = _ctNbioTCommandSenderHelper.SendTapCommand(_CommandMap[commands.MeterNumber], tapStatus);
                //反馈数据包括指令Id
                var nbCommandId = res.commandId;
                //memo赋值
                var nBmemo = new CommandMemoEntity
                {
                    CommandRefId = nbCommandId
                };
                commands.Memo = JsonConvert.SerializeObject(nBmemo);
                var status = res.status;
                var result = CommandCodeMapping.Builder().CodeMapping(status);
                commands.CommandStatus = (int)result;
                return result;
            }

            return CommandStatus.未发送;
        }
    }
}